import os
import shutil
import time
import re
import sqlite3
from typing import List, Iterable
from pathlib import Path
import img2pdf
import jmcomic as jm
from jmcomic import JmOption, DirRule, JmAlbumDetail


class JmManager:
    """
    一个用于搜索、获取信息和下载禁漫漫画的管理器。

    - 负责与 jmcomic API 交互。
    - 负责数据库会话管理。
    - 提供健壮的错误处理和清晰的接口。
    """
    current_dir = Path(__file__).parent
    img_abs_path = (current_dir / "img").absolute()
    pdf_abs_path = (current_dir / "pdf").absolute()
    db_abs_path = (current_dir / "jmcomic.db").absolute()
    comic_list=[]
    def __init__(self, option_file_path=str((current_dir/"option.yml").absolute())):
        """
        初始化 JmManager。
        :param option_file_path: jmcomic 的 option.yml 配置文件路径。
        """
        self.option: JmOption = jm.create_option_by_file(option_file_path)
        # 明确覆盖 option.yml 中的下载目录，确保图片和PDF保存在项目本地
        self.option.dir_rule = DirRule(**{'rule': 'Pid', 'base_dir': str(self.img_abs_path)})
        # self._init_db()
        self.bp=False
        self.name=""
    def _get_db_connection(self):
        """创建并返回一个到SQLite数据库的连接。"""
        conn = sqlite3.connect(self.db_abs_path)
        conn.row_factory = sqlite3.Row
        return conn

    def _init_db(self):
        """如果数据库或表不存在，则初始化数据库和comic表。"""
        try:
            with self._get_db_connection() as conn:
                conn.execute('''
                    CREATE TABLE IF NOT EXISTS comic (
                        id INTEGER PRIMARY KEY,
                        name TEXT NOT NULL
                    )
                ''')
            print(f"数据库 '{self.db_abs_path.name}' 初始化成功。")
        except Exception as e:
            print(f"初始化数据库时出错: {e}")
    def searchName(self,id:str):
        with self._get_db_connection() as conn:
            comic_name = conn.execute(
                'SELECT name FROM comic WHERE id = ?', (id,)
            ).fetchone()
            return comic_name[0] if comic_name else None
    def saveIdtoName(self,id:str):
        with self._get_db_connection() as conn:
            conn.execute(
                'INSERT INTO comic (id, name) VALUES (?, ?)', (id, self.name)
            )
            conn.commit()
    def printname(self,album:JmAlbumDetail,downloader=None):
        self.name=album.name
    def download_albums(self, comic_ids=None, delay_seconds: int = 60):
        """
        根据漫画ID列表下载多个漫画。
        :param comic_ids: 包含漫画ID的可迭代对象（如列表或元组）。
        :param delay_seconds: 每次下载之间的延迟时间（秒）。
        """
        self.bp=True
        if comic_ids is None:
            comic_ids = self.comic_list
        if not comic_ids:
            print("没有要下载的漫画ID。")
            return
        while comic_ids:
            comic_id=comic_ids[0]
            if self.searchName(comic_id) is not None:
                continue
            self.option.download_album(comic_id,callback=self.printname)
            self.saveIdtoName(comic_id)
            comic_ids.pop(0)
            print(f"完成下载，将等待 {delay_seconds} 秒...")
            time.sleep(delay_seconds)
        self.bp=False
    def add_comic_lst(self, comic_id):
        self.comic_list.append(comic_id)

    def download_albums_from_string(self, text_with_ids: str, delay_seconds: int = 60):
        """
        从包含ID的字符串中提取ID并下载对应的漫画。
        :param text_with_ids: 包含漫画ID的多行字符串。
        :param delay_seconds: 每次下载之间的延迟时间（秒）。
        """
        ids_to_download = self._extract_ids_from_text(text_with_ids)
        self.download_albums(ids_to_download, delay_seconds=delay_seconds)

    @staticmethod
    def _extract_ids_from_text(text: str) -> List[str]:
        """
        一个静态辅助方法，从多行文本中提取并连接数字作为ID。
        :param text: 包含ID的字符串。
        :return: 提取出的ID列表（字符串形式）。
        """
        lines = text.splitlines()

        # 使用列表推导式，更简洁
        return [
            "".join(re.findall(r"\d+", line))
            for line in lines
            if re.search(r"\d+", line)  # 只处理包含数字的行
        ]

    @staticmethod
    def folders_images_to_pdfs(
            src_dir=img_abs_path, dst_dir=pdf_abs_path, img_exts=None
    ):
        """
        将src_dir下的所有子文件夹中的图片合成为PDF，输出到dst_dir。
        每个子文件夹生成一个PDF，PDF文件名与子文件夹同名。
        如果目标位置已存在同名PDF，则会跳过。

        :param src_dir: 源文件夹路径
        :param dst_dir: 目标PDF输出路径
        :param img_exts: 图片扩展名列表，默认常见图片格式
        """
        if img_exts is None:
            img_exts = [".jpg", ".jpeg", ".png", ".bmp", ".gif", ".tiff", ".webp"]

        os.makedirs(dst_dir, exist_ok=True)

        if not os.path.isdir(src_dir):
            print(f"错误：源目录 '{src_dir}' 不存在或不是一个目录。")
            return

        for folder in os.listdir(src_dir):
            folder_path = os.path.join(src_dir, folder)

            if os.path.isdir(folder_path):
                # 先定义输出PDF的完整路径
                pdf_path = os.path.join(dst_dir, f"{folder}.pdf")

                # 【新增】判断条件：如果PDF文件已经存在，则打印信息并跳过
                if os.path.exists(pdf_path):
                    print(f"文件已存在，跳过: {pdf_path}")
                    continue

                # 获取所有图片文件，按文件名排序
                imgs = [
                    os.path.join(folder_path, f)
                    for f in sorted(os.listdir(folder_path))
                    if os.path.splitext(f)[1].lower() in img_exts
                ]

                if imgs:
                    print(f"正在创建: {pdf_path}")
                    # 使用 with open 来确保文件正确关闭
                    with open(pdf_path, "wb") as f:
                        f.write(img2pdf.convert(imgs))
                else:
                    print(f"文件夹 '{folder}' 中没有找到支持的图片，跳过。")

    @classmethod
    def clear(cls, path_img=img_abs_path, path_pdf=pdf_abs_path):
        """
        清空图片和PDF目录。
        """
        for item in os.listdir(path_img):
            item_path = os.path.join(path_img, item)
            if os.path.isdir(item_path):
                shutil.rmtree(item_path)

        # for item in os.listdir(path_pdf):
        #     item_path = os.path.join(path_pdf, item)
        #     if os.path.isfile(item_path):
        #         os.remove(item_path)

    def __del__(self):
        """
        在类销毁时，清理临时文件。
        """
        try:
            self.clear()
        except Exception as e:
            print(f"清理临时文件时发生错误: {e}")

comic_downloader = JmManager()
# 使用示例
if __name__ == "__main__":
    option_abs_path = Path(__file__).parent.absolute() / "option.yml"
    Jm = JmManager(str(option_abs_path))
    Jm.download_albums(["1205735"])